package auth

import (
	"context"
	"strconv"
	"strings"
	"time"

	"mall/common/globalkey"
	"mall/common/modelx"
	"mall/common/resultx"
	"mall/service/user/model"
	"mall/service/user/rpc/internal/svc"
	"mall/service/user/rpc/types/user"

	"github.com/volatiletech/null/v8"
	"github.com/zeromicro/go-zero/core/logx"
)

type UpdateUserAuthInfoLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewUpdateUserAuthInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UpdateUserAuthInfoLogic {
	return &UpdateUserAuthInfoLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *UpdateUserAuthInfoLogic) UpdateUserAuthInfo(in *user.TmpUserAuthInfo) (*user.UpdateUserAuthResp, error) {
	if (in.UserId == nil || *in.UserId == 0) && (in.UserUUID == nil || len(strings.TrimSpace(*in.UserUUID)) == 0) {
		return nil, resultx.StatusError(resultx.USER_AUTH_PARAM_INVALID, "")
	}

	var userId uint64
	if in.UserId != nil && *in.UserId > 0 {
		userId = *in.UserId
	} else if i, err := strconv.ParseInt(strings.TrimSpace(*in.UserUUID), 10, 64); err == nil && i > 0 {
		userId = uint64(i)
	} else {
		return nil, resultx.StatusError(resultx.USER_AUTH_PARAM_INVALID, "")
	}

	if in.PlatformId == nil || *in.PlatformId == 0 {
		return nil, resultx.StatusError(resultx.USER_AUTH_PARAM_INVALID, "")
	}

	platformId := *in.PlatformId

	// 查询用户是否存在
	_, err := l.svcCtx.CurrentUser.FindOne(l.ctx, userId)
	if err != nil {
		return nil, err
	}
	filterMap := make(map[string]map[string][]any)
	filterMap[model.UserAuthColumns.PlatformID] = map[string][]any{
		"equalTo": {platformId},
	}
	filterMap[model.UserAuthColumns.UserID] = map[string][]any{
		"equalTo": {userId},
	}
	authList, _, err := l.svcCtx.CurrentUser.GetAuthList(l.ctx, model.M{
		"pageSize": uint64(1),
	}, -1, filterMap)
	if err != nil {
		return nil, err
	}

	if len(authList) == 0 {
		return nil, resultx.StatusError(resultx.USER_AUTH_PARAM_INVALID, "")
	}

	userAuth := authList[0]

	detailFilterMap := make(map[string]map[string][]any)
	detailFilterMap[model.UserDetailColumns.UserID] = map[string][]any{
		"equalTo": {userId},
	}
	detailList, _, err := l.svcCtx.CurrentUser.GetDetailList(l.ctx, model.M{
		"pageSize": uint64(1),
	}, -1, detailFilterMap)
	if err != nil {
		return nil, err
	}

	var userDetail *model.UserDetail
	if len(detailList) > 0 {
		userDetail = detailList[0]
	}

	var userMeta []*model.UserMetum
	var userMedia []*model.UserAttachmentRelationship

	tx, err := l.svcCtx.DB.BeginTx(l.ctx, nil)
	if err != nil {
		return nil, resultx.StatusError(resultx.DB_ERROR, "")
	}

	now := time.Now()
	userAuth.UpdatedAt = now
	if in.Nickname != nil && len(strings.TrimSpace(*in.Nickname)) > 0 {
		nickname := strings.TrimSpace(*in.Nickname)
		userAuth.Nickname = nickname
		if userDetail != nil {
			userDetail.Nickname = nickname
		}
	}
	if in.Avatar != nil && len(strings.TrimSpace(*in.Avatar)) > 0 {
		avatar := strings.TrimSpace(*in.Avatar)
		userAuth.Avatar = avatar
		if userDetail != nil {
			userDetail.Avatar = avatar
		}
	}
	if in.Gender != nil && *in.Gender > 0 {
		userAuth.Gender = uint8(*in.Gender)
		if userDetail != nil {
			userDetail.Gender = userAuth.Gender
		}
	}
	if in.Birthday != nil && len(strings.TrimSpace(*in.Birthday)) > 0 {
		if localTime, err := modelx.ParseLocalDate(strings.TrimSpace(*in.Birthday)); err == nil {
			userAuth.Birthday = null.TimeFrom(localTime)
			if userDetail != nil {
				userDetail.Birthday = userAuth.Birthday
			}
		}
	}
	// if in.BirthdayHidden != nil && *in.BirthdayHidden > 0 {
	// 	userMeta = append(userMeta, &model.UserMetum{
	// 		MetaKey:   "_birthday_hidden",
	// 		MetaValue: null.StringFrom("1"),
	// 	})
	// }
	// Todo: BirthdayHidden 待处理

	if len(in.NewMedia) > 0 {
		mediaFilterMap := make(map[string]map[string][]any)
		mediaFilterMap[model.UserAttachmentRelationshipColumns.UserID] = map[string][]any{
			"equalTo": {userId},
		}
		mediaFilterMap[model.UserAttachmentRelationshipColumns.Type] = map[string][]any{
			"equalTo": {globalkey.AttachmentLogTypeUserAvatar},
		}
		media, _, err := l.svcCtx.CurrentUser.GetMedia(l.ctx, model.M{}, -1, mediaFilterMap)
		if err != nil {
			return nil, err
		}

		mediaMap := make(map[uint64]*model.UserAttachmentRelationship)
		mediaUidMap := make(map[uint64]*model.UserAttachmentRelationship)
		if len(media) > 0 {
			for _, v := range media {
				mediaMap[v.AttachmentID] = v
				mediaUidMap[v.AttachmentRelationshipID] = v
			}
		}

		for idx, v := range in.NewMedia {
			var url string
			if v.Url != nil && len(*v.Url) > 0 { //最终网址
				url = *v.Url
			}
			if len(url) == 0 && v.Uri != nil && len(*v.Uri) > 0 { //临时网址
				url = *v.Uri
			}
			if len(url) == 0 {
				continue
			}

			var thumbnail uint8
			if v.Thumbnail != nil && *v.Thumbnail > 0 {
				thumbnail = uint8(*v.Thumbnail)
			}
			var order uint
			if v.Order != nil {
				order = uint(*v.Order)
			} else {
				order = uint(idx) + globalkey.AttachmentOrderOffset
			}
			var altText string
			if v.AltText != nil && len(*v.AltText) > 0 {
				altText = *v.AltText
			}
			var meta []string
			if v.Name != nil && len(*v.Name) > 0 {
				meta = append(meta, "filename:"+*v.Name)
				if len(altText) == 0 {
					altText = *v.Name
				}
			}
			if v.MetaData != nil && len(*v.MetaData) > 0 {
				meta = append(meta, *v.MetaData)
			}
			// if v.MimeType != nil && len(*v.MimeType) > 0 {
			// 	meta = append(meta, "mimeType:"+*v.MimeType)
			// }
			metaData := strings.Join(meta, ";")

			var mediaId uint64
			if v.Id != nil && len(*v.Id) > 0 {
				// mediaId = *v.Id
				if i, err := strconv.ParseInt(*v.Id, 10, 64); err == nil {
					mediaId = uint64(i)
				}
			}
			var uid uint64
			if v.Uid != nil && *v.Uid > 0 {
				uid = *v.Uid
			}

			// Todo： 暂不做删除

			if uid > 0 {
				if _, ok := mediaUidMap[uid]; ok { //已存在，修改
					userMedia = append(userMedia, &model.UserAttachmentRelationship{
						AttachmentRelationshipID: uid,
						AttachmentID:             mediaId,
						AttachmentThumbnail:      thumbnail,
						AttachmentOrder:          order,
						AttachmentImageURL:       url,
						AttachmentImageAlt:       altText,
						AttachmentImageMeta:      metaData,
					})
				}
				continue
			}

			userMedia = append(userMedia, &model.UserAttachmentRelationship{
				Type:                uint16(globalkey.AttachmentLogTypeUserAvatar),
				AttachmentID:        mediaId,
				AttachmentThumbnail: thumbnail,
				AttachmentOrder:     order,
				AttachmentImageURL:  url,
				AttachmentImageAlt:  altText,
				AttachmentImageMeta: metaData,
			})
		}
	}

	err = l.svcCtx.CurrentUser.Update(l.ctx, tx, nil, &model.UserRel{
		Auth:   userAuth,
		Detail: userDetail,
		Meta:   userMeta,
		Media:  userMedia,
	})
	if err != nil {
		tx.Rollback()
		return nil, resultx.StatusError(resultx.USER_AUTH_MODIFY_FAILED, "")
	}

	tx.Commit()

	return &user.UpdateUserAuthResp{}, nil
}
